/*************************************
 * gpio2为0时NC供电，为1时停电
 *
 * *******************************/
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
WiFiUDP ntpUDP;
// NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 8 * 3600, 60000);
NTPClient timeClient(ntpUDP, "ntp.aliyun.com", 8 * 3600, 60000);

// const char *mqtt_server = "192.168.3.254";
// const char *mqtt_server = "lubo1982.mycloudnas.com";
//const char *mqtt_server = "325p3976r5.qicp.vip";
const char *mqtt_server = "lubo1982.mycloudnas.com";
const char *mqttUser = "lu";
const char *mqttPassWd = "5891381";
const int port = 1883;
char pubTopic[20], subTopic[20], msgTopic[20];
unsigned long lastTime = 0;
WiFiClient espClient;
PubSubClient client(espClient);
String Host;
bool move = 0;
u_char today;
int moveTimes = 0;
struct dateTime
{
    int year;
    u_char month;
    u_char date;
    u_char day;
    u_char hour;
    u_char minute;
    u_char second;
};
dateTime dt;
dateTime firstMove;

dateTime timeSync()
{
    dateTime dt;
    unsigned long epochTime;
    timeClient.update();
    epochTime = timeClient.getEpochTime();

    dt.year = year(epochTime);
    dt.month = month(epochTime);
    dt.date = day(epochTime);
    dt.day = weekday(epochTime);
    dt.hour = hour(epochTime);
    dt.minute = minute(epochTime);
    dt.second = second(epochTime);
    return dt;
}
void callback(char *topic, byte *payload, unsigned int length)
{
    Serial.print("R[");
    Serial.print(topic);
    Serial.print("]:");
    String message;
    for (int i = 0; i < length; i++)
    {
        message += ((char)payload[i]);
    }
    Serial.println(message);

    // Switch on the LED if an 1 was received as first character
    // if (strcmp(topic, subTopic) == 0)

    if (message == "1")
    {
        digitalWrite(2, 0);
    }
    if (message == "0")
    {
        digitalWrite(2, 1);
    }
    client.publish(pubTopic, digitalRead(2) ? "Off" : "On");
    Serial.printf("T[%s]:%s\n", pubTopic, digitalRead(2) ? "1" : "0");
}

void reconnect()
{
    // Loop until we're reconnected
    do

    {
        Serial.print("Attempting MQTT connection...");
        if (client.connect(Host.c_str(), mqttUser, mqttPassWd))
        {
            Serial.println("connected");
            // Once connected, publish an announcement...
        }
        else
        {
            Serial.print("failed, rc=");
            Serial.print(client.state());
            Serial.println(" try again in 5 seconds");
            // Wait 5 seconds before retrying
            delay(5000);
        }
    } while (!client.connect(Host.c_str(), mqttUser, mqttPassWd));
    subscribe();
    blink(5);
    client.publish(msgTopic, "MQTT server reconnected");
}
void subscribe()
{
    client.subscribe(subTopic);
}
void IRAM_ATTR moved()
{
    move = 1;
}
void blink(int times)
{
    for (times; times > 0; times--)
    {
        digitalWrite(2, 0);
        delay(100);
        digitalWrite(2, 1);
        delay(100);
    }
}
void setup()
{
    uint8_t macAddr[6];
    WiFi.macAddress(macAddr);
    pinMode(5, INPUT);
    pinMode(2, OUTPUT);
    digitalWrite(2, 1);
    //   digitalWrite(2, 0);
    Serial.begin(115200);
    WiFiManager wifiManager;
    wifiManager.setTimeout(180);
    char ap[10];
    sprintf(ap, "Switch-%X%X%X", macAddr[3], macAddr[4], macAddr[5]);
    Host = "Switch" + macAddr[4] + macAddr[5];
    WiFi.hostname(Host.c_str());
    sprintf(pubTopic, "%X%X%X/Status", macAddr[3], macAddr[4], macAddr[5]);
    sprintf(subTopic, "%X%X%X/Cmd", macAddr[3], macAddr[4], macAddr[5]);
    sprintf(msgTopic, "%X%X%X/Msg", macAddr[3], macAddr[4], macAddr[5]);

    //   wifiManager.resetSettings();
    if (!wifiManager.autoConnect(ap))
    {
        Serial.println("failed to connect and hit timeout");
        delay(3000);
        ESP.reset();
        delay(5000);
    }
    Serial.println("WIFI connected");
    blink(3);
    delay(3000);
    client.setServer(mqtt_server, 1883);
    client.setCallback(callback);
    reconnect();
    attachInterrupt(5, moved, RISING);
    today = 50;
    firstMove.hour = 0;
    firstMove.minute = 0;
    firstMove.second = 0;
}

void loop()
{

    char msg[50];
    if (!client.connected())
    {
        reconnect();
    }
    client.loop();

    if (move == 1)
    {
        move = 0;

        dt = timeSync();
        if (dt.date != today)
        {
            today = dt.date;
            firstMove = timeSync();
            moveTimes = 0;
        }
        moveTimes++;
        blink(1);
    }
    if (millis() - lastTime > 5000)
    {
        sprintf(msg, "{\"first\":\"%02d:%02d:%02d\",\"last\":\"%02d:%02d:%02d\",\"total\":%d}", firstMove.hour, firstMove.minute, firstMove.second, dt.hour, dt.minute, dt.second, moveTimes);
        client.publish(pubTopic, msg);
        Serial.printf("T[%s]:%s\n", pubTopic, msg);
    }
}
